# GPL3 or any later version

import os
import json
import gi
import time
import threading
import datetime

gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import GLib

from modules import graphs
from modules import wallet
from modules import transactions

def EDB(payday, balance, today):

    # Estimated Daily Budget.

    date_format = "%Y/%m/%d"

    datetime_today = datetime.datetime.strptime(today, date_format)

    
    if payday < datetime_today.day:
        nm = int(datetime_today.month)
        nm = nm + 1
        if nm > 12:
            nm = 1
        nm = str(nm)
        if len(nm) < 2:
            nm = "0"+nm
        nextm = today[:today.find("/")+1]+nm+today[today.rfind("/"):]
    else:
        nextm = today
        
    # Converting
    payday = str(payday)
    if len(payday) < 2:
        payday = "0"+payday

    payday = nextm[:nextm.rfind("/")+1]+payday
    tpayday = datetime.datetime.strptime(payday, date_format)
    days_between = int((tpayday - datetime_today).days)

    try:
        mpd = balance / days_between
    except:
        mpd = balance
    return mpd
    


def update_totals(win):

    # Updates the totals view

    box = win.totals_box
    the_wallet = win.wallet
    
    for i in box.get_children():
        i.destroy()
    
    data = wallet.get_totals(the_wallet)
    print(data)

    # Important settings
    currancy = data.get("currancy", "$")
    payday = data.get("payday", 10)
    
    try:
        int(payday)
    except:
        payday = 10
    
    

    # loading balance
    balance = 0
    balance_before_today = 0
    balance_of_today = 0

    graph_data = {"items":[],
                  "zoom":[int(time.time()-(60*60*24*365/4)), # One Quarter of a year
                          int(time.time())],
                  "allow_negative":True
        }

    pulse_graph_data = {"items":[],
                  "zoom":[int(time.time()-(60*60*24*365/4)), # One Quarter of a year
                          int(time.time())],
                  "allow_negative":True
        }

    EDB_graph_data = {"items":[],
                  "zoom":[int(time.time()-(60*60*24*365/4)), # One Quarter of a year
                          int(time.time())],
                  "allow_negative":True
        }

    EDB_leftovers_graph_data = {"items":[],
                  "zoom":[int(time.time()-(60*60*24*365/4)), # One Quarter of a year
                          int(time.time())],
                  "allow_negative":True
        }
    
    folder = wallet.save_folder()+"wallets/"+win.wallet+"/transactions/"
    try:
        transactions = list(os.walk(folder))[0][2]
        transactions = sorted(transactions)
    except:
        transactions = []

    pre_date = "0000/00/00"
    dates_EDB = 0
    balance_at_EDB = 0
    leftover = 0
    for i in transactions:
        try:
            with open(folder+i) as json_file: 
                tdata = json.load(json_file)

            timestamp = int(i.replace(".json", ""))

            date_format = "%Y/%m/%d"
            
            date_of_transaction = time.strftime(date_format, time.gmtime(timestamp))
            today = time.strftime(date_format, time.gmtime(time.time()))

            prebalance = balance
            balance = balance + tdata.get("total", 0)

            
            if date_of_transaction != today:
                balance_before_today = balance
            else:
                balance_of_today = balance_of_today + tdata.get("total", 0)

            # Balance Graph
            a = {}
            a["amount"] = balance
            a["timestamp"] = timestamp

            graph_data["items"].append(a)

            # Pulse Graph
            
            a = {}
            a["amount"] = tdata.get("total", 0)
            a["timestamp"] = timestamp

            pulse_graph_data["items"].append(a)

            # EDB Graph
            
            if date_of_transaction != pre_date:

                dates_EDB = EDB(payday, prebalance, date_of_transaction)
                balance_at_EDB = prebalance
                
                a = {}
                a["amount"] = dates_EDB
                a["timestamp"] = timestamp

                EDB_graph_data["items"].append(a)
                print()

            
                
            leftover = balance - balance_at_EDB + dates_EDB
                
            a = {}
            a["amount"] = leftover
            a["timestamp"] = timestamp
            
            EDB_leftovers_graph_data["items"].append(a)

                
            pre_date = date_of_transaction
            
            
        except Exception as e:
            print(e)
        
    balance = round(balance, 2)
            
    balance_label = Gtk.Label()
    balance_label.set_line_wrap_mode( Gtk.WrapMode.WORD )
    balance_label.set_line_wrap(True)
    balance_label.set_markup('<span size="x-large">  '+currancy+str(balance)+'</span> ')
    balance_label.set_selectable(True)
    balance_label.set_css_name("")

    def on_balance_button(w):
        balance_calculator(win, balance)
    
    balance_button = Gtk.Button()
    balance_button.add(balance_label)
    balance_button.set_relief(Gtk.ReliefStyle.NONE)
    balance_button.connect("clicked", on_balance_button)

    box.pack_start(balance_button, 0,0,10)

    # Money per day till pay day

    
    date_format = "%Y/%m/%d"
    today = datetime.datetime.strftime(datetime.datetime.today(), date_format)

    mpd = EDB(payday, balance_before_today, today)

    show_mpd = currancy+str(round(mpd, 2))+" : yesterday's estimated daily budget (EDB)"
    box.pack_start(Gtk.Label(show_mpd), 0,0,10)
    

    # Today used

    show_today_user = currancy+str(round(balance_of_today, 2))+" : today's difference"
    box.pack_start(Gtk.Label(show_today_user), 0,0,10)

    # Left for today
    show_left_for_today = currancy+str(round(mpd+balance_of_today, 2))+" : today's budget"
    box.pack_start(Gtk.Label(show_left_for_today), 0,0,10)

    
    edb = EDB(payday, balance, today)

    
    show_mpd = currancy+str(round(edb, 2))+" : estimated daily budget (EDB)"
    box.pack_start(Gtk.Label(show_mpd), 0,0,10)

    # Notebook
    notebook = Gtk.Notebook()
    notebook.set_scrollable(True)
    box.pack_start(notebook, 1,1,10)
    
    the_graph = graphs.graph(win, graph_data, "Balance", currancy=currancy, graph_addition="last")

    detailsbox = Gtk.HBox()
    detailsbox.pack_start(Gtk.Label("  Balance  "), True, True, True)
    detailsbox.show_all()
    notebook.append_page(the_graph, detailsbox)
    
    pulse_graph = graphs.graph(win, pulse_graph_data, "Pulse", currancy=currancy, graph_addition="add", add_value=0)

    detailsbox = Gtk.HBox()
    detailsbox.pack_start(Gtk.Label("  Difference  "), True, True, True)
    detailsbox.show_all()
    notebook.append_page(pulse_graph, detailsbox)


    edb_graph = graphs.graph(win, EDB_graph_data, "EDB", currancy=currancy, graph_addition="last")

    detailsbox = Gtk.HBox()
    detailsbox.pack_start(Gtk.Label("  EDB  "), True, True, True)
    detailsbox.show_all()
    notebook.append_page(edb_graph, detailsbox)

    leftovers_graph = graphs.graph(win, EDB_leftovers_graph_data, "gains", currancy=currancy, graph_addition="last", add_value=0)

    detailsbox = Gtk.HBox()
    detailsbox.pack_start(Gtk.Label("  Gains / Losses  "), True, True, True)
    detailsbox.show_all()
    notebook.append_page(leftovers_graph, detailsbox)
    
    box.show_all()


def balance_calculator(win, balance):

    # This window will help people calculate the money.

    dialogWindow = Gtk.Dialog("Balance Calculator",
            buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
                     Gtk.STOCK_OK, Gtk.ResponseType.OK),
        )
    dialogWindow.set_size_request(200, 200)

    data = wallet.get_totals(win.wallet)
    currancy = data.get("currancy", "$")

    
    box = dialogWindow.get_content_area()

    # Types of coins
    amounts = [0.01,
               0.1,
               0.25,
               0.5,
               1,
               2,
               5,
               10,
               20,
               50,
               100,
               200,
               500,
               1000]

    wdg = []

    def calculate(w):
        b = 0
        for n, i in enumerate(wdg):
            b = b + ( i[1].get_value() * amounts[n])

        total_amount_entry.set_value(b)
    
    for n, coin in enumerate(amounts):

        abox = Gtk.HBox()
        box.pack_start(abox, 0,0,5)
        abox.pack_start(Gtk.Label(currancy+" "+str(coin)), 0,0,10)

        amount_adjust = Gtk.Adjustment(0,
                                       lower=-10000000000000000000,
                                       upper=10000000000000000000,
                                       step_increment=1) 
        amount_entry  = Gtk.SpinButton(adjustment=amount_adjust,
                                       digits=0)
        abox.pack_end(amount_entry, 0,0,10)
        amount_entry.connect("changed", calculate)
        wdg.append([amount_adjust, amount_entry])


    box.pack_start(Gtk.HSeparator(), 0,0,10)

    abox = Gtk.HBox()
    box.pack_start(abox, 0,0,5)
    abox.pack_start(Gtk.Label("Total: "+currancy+" "), 0,0,10)
    
    total_amount_adjust = Gtk.Adjustment(0,
                                   lower=-10000000000000000000,
                                   upper=10000000000000000000,
                                   step_increment=1) 
    total_amount_entry  = Gtk.SpinButton(adjustment=total_amount_adjust,
                                   digits=2)
    abox.pack_end(total_amount_entry, 0,0,10)
    
    
    
    box.show_all()
    
    response = dialogWindow.run()
    if response == Gtk.ResponseType.OK:


        name = str(int(time.time()))+".json"
        the_wallet = win.wallet
        folder = wallet.save_folder()+"wallets/"+the_wallet+"/transactions/"
        tfile = folder+name

        comment = "Calculated Balance:\n"

        for n, i in enumerate(wdg):

            v = i[1].get_value()
            if v:
                comment = comment +"\n"+currancy+" "+str(amounts[n])+" X "+str(int(v))

        comment = comment + "\n\nTotal: "+currancy+" "+str(total_amount_entry.get_value())
        comment = comment + "\nError: "+currancy+" "+str(total_amount_entry.get_value()-balance)
        
        transaction = {
            "items": [
                {
                    "item": "count_feature",
                    "amount": 1,
                    "price": total_amount_entry.get_value()-balance
                }
            ],
            "total": total_amount_entry.get_value()-balance,
            "comment":comment
        }

        with open(tfile, "w") as fp:
            json.dump(transaction, fp, indent=4)

        transactions.update_transactions(win)
        update_totals(win)


    dialogWindow.destroy()

    
